﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CombineProto
{
    public class EnumToProto : CombineProto
    {
        private MessageEnum m_luaSCCmd;
        private MessageEnum m_luaCSCmd;
        private MessageEnum m_cSharpSCCmd;
        private MessageEnum m_cSharpCSCmd;
        private int csharpMaxValue;
        private int luaMaxValue;
        public EnumToProto(GenerateConfig config) : base(config)
        {
        }
        public void GenerateAll()
        {
            AynalizeProto();
            List<string> cmessagetypes = new List<string>();
            List<string> luamessagetypes = new List<string>();
            MessageEnum cMessage = null;
            MessageEnum luaMessage = null;
            int count = 0;
            csharpMaxValue = Convert.ToInt32(p_config.csharpMaxValue);
            luaMaxValue = Convert.ToInt32(p_config.luaMaxValue);
            for (int i = 0; i < p_allEnums.Count; i++)
            {
                if (p_allEnums[i].name.Equals(p_config.csCmdEnumName) || p_allEnums[i].name.Equals(p_config.scCmdEnumName))
                {
                    count++;
                    cMessage = new MessageEnum();
                    cMessage.name = p_allEnums[i].name;
                    luaMessage = new MessageEnum();
                    luaMessage.name = p_allEnums[i].name;
                    for (int j = 0; j < p_allEnums[i].dots.Count; j++)
                    {
                        EnumValue d = p_allEnums[i].dots[j];
                        int val = int.Parse(d.value);
                        if (val < csharpMaxValue)
                        {
                            if (string.IsNullOrEmpty(p_config.scCmdPreExtension) || string.IsNullOrEmpty(p_config.csCmdPreExtension))
                            {
                                cmessagetypes.Add(d.name);
                            }
                            else
                            {
                                cmessagetypes.Add(d.name.Replace(p_config.scCmdPreExtension, "").Replace(p_config.csCmdPreExtension, ""));
                            }
                            cMessage.dots.Add(d);
                        }
                        else if (val >= csharpMaxValue && val < luaMaxValue)
                        {
                            if (string.IsNullOrEmpty(p_config.scCmdPreExtension) || string.IsNullOrEmpty(p_config.csCmdPreExtension))
                            {
                                luamessagetypes.Add(d.name);
                            }
                            else
                            {
                                luamessagetypes.Add(d.name.Replace(p_config.scCmdPreExtension, "").Replace(p_config.csCmdPreExtension, ""));
                            }
                            luaMessage.dots.Add(d);
                        }
                    }

                    if (luaMessage.name.Equals(p_config.scCmdEnumName))
                    {
                        m_luaSCCmd = luaMessage;
                    }
                    else if (luaMessage.name.Equals(p_config.csCmdEnumName))
                    {
                        m_luaCSCmd = luaMessage;
                    }

                    if (cMessage.name.Equals(p_config.scCmdEnumName))
                    {
                        m_cSharpSCCmd = cMessage;
                    }
                    else if (cMessage.name.Equals(p_config.csCmdEnumName))
                    {
                        m_cSharpCSCmd = cMessage;
                    }
                }
                if (count >= 2)
                {
                    break;
                }
            }
            if (m_cSharpCSCmd == null)
            {
                throw new Exception("dont has this enum: " + p_config.scCmdEnumName);
            }
            if (m_cSharpCSCmd == null)
            {
                throw new Exception("dont has this enum: " + p_config.csCmdEnumName);
            }
            m_cSharpSCCmd.RemoveGreater(csharpMaxValue);
            m_cSharpCSCmd.RemoveGreater(csharpMaxValue);
            p_cEnums.Add(m_cSharpSCCmd);
            p_cEnums.Add(m_cSharpCSCmd);
            m_luaCSCmd.RemoveLower(csharpMaxValue);
            m_luaSCCmd.RemoveGreater(luaMaxValue);
            p_luaEnums.Add(m_luaCSCmd);
            p_luaEnums.Add(m_luaSCCmd);
            for (int i = 0; i < cmessagetypes.Count; i++)
            {
                AddCMessage(cmessagetypes[i]);
            }

            for (int i = 0; i < luamessagetypes.Count; i++)
            {
                AddLuaMessage(luamessagetypes[i]);
            }
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaDistRelatePath), ToLuaPbFile());
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.csharpDistRelatePath), ToCSDll());
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaCSCmdReplatePath), ToLuaCSCmdFile());
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaSCCmdReplatePath), ToLuaSCCmdFile());
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaAnnotationPath), ToLuaAnnotationFile());
            //Console.WriteLine(Path.Combine(System.Environment.CurrentDirectory, m_config.luaCompilePath));
            //Console.WriteLine(Path.Combine(System.Environment.CurrentDirectory, m_config.csCompilePath));
            //string err1 = RunBat(Path.Combine(System.Environment.CurrentDirectory, m_config.luaCompilePath), m_config.luaCompileArguments);
            //string err2 = RunBat(Path.Combine(System.Environment.CurrentDirectory, m_config.csCompilePath), m_config.csCompileArguments);

            //callback(err1 + err2);
        }
        public void GenerateLua(Action<string> callback)
        {
            AynalizeProto();
            List<string> luamessagetypes = new List<string>();
            MessageEnum luaMessage = null;
            int count = 0;
            for (int i = 0; i < p_allEnums.Count; i++)
            {
                if (p_allEnums[i].name.Equals(p_config.csCmdEnumName) || p_allEnums[i].name.Equals(p_config.scCmdEnumName))
                {
                    count++;
                    luaMessage = new MessageEnum();
                    luaMessage.name = p_allEnums[i].name;
                    for (int j = 0; j < p_allEnums[i].dots.Count; j++)
                    {
                        EnumValue d = p_allEnums[i].dots[j];
                        int val = int.Parse(d.value);
                        if (val >= csharpMaxValue && val < luaMaxValue)
                        {
                            if (string.IsNullOrEmpty(p_config.scCmdPreExtension) || string.IsNullOrEmpty(p_config.csCmdPreExtension))
                            {
                                luamessagetypes.Add(d.name);
                            }
                            else
                            {
                                luamessagetypes.Add(d.name.Replace(p_config.scCmdPreExtension, "").Replace(p_config.csCmdPreExtension, ""));
                            }
                            luaMessage.dots.Add(d);
                        }
                    }

                    if (luaMessage.name.Equals(p_config.scCmdEnumName))
                    {
                        m_luaSCCmd = luaMessage;
                    }
                    else if (luaMessage.name.Equals(p_config.csCmdEnumName))
                    {
                        m_luaCSCmd = luaMessage;
                    }
                }
                if (count >= 2)
                {
                    break;
                }
            }
            m_luaCSCmd.RemoveLower(csharpMaxValue);
            m_luaSCCmd.RemoveGreater(luaMaxValue);
            p_luaEnums.Add(m_luaCSCmd);
            p_luaEnums.Add(m_luaSCCmd);

            for (int i = 0; i < luamessagetypes.Count; i++)
            {
                AddLuaMessage(luamessagetypes[i]);
            }
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaDistRelatePath), ToLuaPbFile());
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaCSCmdReplatePath), ToLuaCSCmdFile());
            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.luaSCCmdReplatePath), ToLuaSCCmdFile());

            //string err1 = RunBat(Path.Combine(System.Environment.CurrentDirectory, m_config.luaCompilePath), m_config.luaCompileArguments);
            //callback(err1);
        }
        public void GenerateCSharp()
        {
            AynalizeProto();
            List<string> messagetypes = new List<string>();
            MessageEnum cMessage = null;
            int count = 0;
            for (int i = 0; i < p_allEnums.Count; i++)
            {
                if (p_allEnums[i].name.Equals(p_config.csCmdEnumName) || p_allEnums[i].name.Equals(p_config.scCmdEnumName))
                {
                    count++;
                    cMessage = new MessageEnum();
                    cMessage.name = p_allEnums[i].name;
                    for (int j = 0; j < p_allEnums[i].dots.Count; j++)
                    {
                        EnumValue d = p_allEnums[i].dots[j];
                        int val = int.Parse(d.value);
                        if (val < csharpMaxValue)
                        {
                            if (string.IsNullOrEmpty(p_config.scCmdPreExtension) || string.IsNullOrEmpty(p_config.csCmdPreExtension))
                            {
                                messagetypes.Add(d.name);
                            }
                            else
                            {
                                messagetypes.Add(d.name.Replace(p_config.scCmdPreExtension, "").Replace(p_config.csCmdPreExtension, ""));
                            }
                            cMessage.dots.Add(d);
                        }
                    }

                    if (cMessage.name.Equals(p_config.scCmdEnumName))
                    {
                        m_cSharpSCCmd = cMessage;
                    }
                    else if (cMessage.name.Equals(p_config.csCmdEnumName))
                    {
                        m_cSharpCSCmd = cMessage;
                    }
                }
                if (count >= 2)
                {
                    break;
                }
            }
            m_cSharpSCCmd.RemoveGreater(csharpMaxValue);
            m_cSharpCSCmd.RemoveGreater(csharpMaxValue);
            p_cEnums.Add(m_cSharpSCCmd);
            p_cEnums.Add(m_cSharpCSCmd);
            for (int i = 0; i < messagetypes.Count; i++)
            {
                AddCMessage(messagetypes[i]);
            }

            SaveFile(Path.Combine(System.Environment.CurrentDirectory, p_config.csharpDistRelatePath), ToCSDll());

            //string err2 = RunBat(Path.Combine(System.Environment.CurrentDirectory, m_config.csCompilePath), m_config.csCompileArguments);
            //callback(err2);
        }
        private string ToCSDll()
        {
            string ret = string.Empty;
            if (p_cEnums.Count > 0)
            {
                for (int i = 0; i < p_cEnums.Count; i++)
                {
                    ret += "\n\n" + p_cEnums[i].ToString();
                }
            }
            for (int i = 0; i < p_cMessages.Count; i++)
            {
                ret += "\n\n" + p_cMessages[i].ToString();
            }
            return string.Format("package {0};{1}", p_config.packageName, ret);
        }
        private string ToLuaPbFile()
        {
            string ret = string.Empty;
            for (int i = 0; i < p_luaEnums.Count; i++)
            {
                ret += "\n\n" + p_luaEnums[i].ToString();
            }
            for (int i = 0; i < p_luaMessages.Count; i++)
            {
                ret += "\n\n" + p_luaMessages[i].ToString();
            }
            return string.Format("package {0};{1}", p_config.packageName, ret);
        }
        private string ToLuaCSCmdFile()
        {
            string ret = "--【协议号文件】由脚本自动产生，避免手动修改内容\n\n--协议包名\n";
            ret += "local package = \"" + p_config.packageName + "\";\n";
            ret += m_luaCSCmd.ToLuaCmd();
            return ret;
        }
        private string ToLuaSCCmdFile()
        {
            string ret = "--【协议号文件】由脚本自动产生，避免手动修改内容\n\n--协议包名\n";
            ret += "local package = \"" + p_config.packageName + "\";\n";
            ret += m_luaSCCmd.ToLuaCmd();
            return ret;
        }

        private string ToLuaAnnotationFile()
        {
            string ret = "--【协议号文件注释】由脚本自动生成，避免手动修改\n";
            for (int i = 0; i < p_luaMessages.Count; i++)
            {
                ret += "\n\n" + p_luaMessages[i].ToLuaAnnotation();
            }
            return ret;
        }
    }
}